package cn.dengta.context.web;

import java.util.Date;
import java.util.List;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;

import cn.dengta.common.context.*;
import cn.dengta.common.model.TimeInterval;
import cn.dengta.common.security.SecurityUtil;
import cn.dengta.common.web.*;
import cn.dengta.common.web.mvc.BaseProxyRequest;
import cn.dengta.common.web.mvc.DateConverter;
import cn.dengta.context.auth.ExportInterceptor;
import cn.dengta.context.model.*;
import me.codeplayer.util.StringUtil;
import me.codeplayer.util.X;
import org.apache.commons.lang3.StringUtils;

public class ProxyRequest extends BaseProxyRequest {

	/**
	 * 获取当前session的用户对象<br>
	 * 如果用户未登录，则返回 null
	 */
	public <U extends Member> U getSessionUser() {
		return RequestContext.getSessionUser(request);
	}

	/**
	 * 获取语言
	 */
	public Language sessionLanguage() {
		return RequestContextImpl.get().sessionLanguage();
	}

	/**
	 * 获取请求头数据
	 */
	public String getHeader(String head) {
		return request.getHeader(head);
	}

	/**
	 * 获取当前操作时间
	 */
	public Date now() {
		return RequestContextImpl.get().now();
	}

	/**
	 * 设置当前session的用户对象
	 */
	public void setSessionUser(Member user) {
		RequestContext.setSessionUser(request, user);
	}

	/**
	 * 清空当前session中存储的用户对象
	 */
	public void removeSessionUser() {
		removeSessionAttr(RequestContext.SESSION_USER);
	}

	/**
	 * 返回来源地址<br>
	 * 如果从登录页跳转的链接，或者新开窗口导致没有获取到来源地址，则返回null
	 */
	public String getSessionReferer() {
		Object referer = sessionAttr("referer");
		String ref = referer == null ? null : referer.toString();
		if (referer != null && !ref.contains("login")) {
			return ref;
		}
		return null;// 如果从登录页或者新开一个页面进入操作页，进行操作后，默认跳转至首页。
	}

	/**
	 * 获取邀请码<br>
	 * 本方法先通过session获取邀请码，再通过request获取邀请码参数
	 *
	 * @since 1.0
	 */
	public final String getInviteCode() {
		InternalConfig cfg = Context.internal();
		String inviteCode = getInviteCodeInternal(cfg);
		if (StringUtil.isEmpty(inviteCode)) {
			Object o = sessionAttr(cfg.getInviteCodeSessionAttr());
			if (o != null) {
				inviteCode = o.toString();
			}
		} else {
			inviteCode = inviteCode.trim();
			// 防御 XSS
			if (!SecurityUtil.inviteCodeSafeCheck(inviteCode)) {
				return null;
			}
		}
		return inviteCode;
	}

	protected String getInviteCodeInternal(InternalConfig cfg) {
		String name = cfg.getInviteCodeParamName();
		String inviteCode = request.getParameter(name);
		if (StringUtil.isEmpty(inviteCode)) {
			String attr = cfg.getInviteCodeSessionAttr();
			if (StringUtil.notEmpty(attr) && !name.equals(attr)) {
				inviteCode = request.getParameter(attr);
			}
		}
		return inviteCode;
	}

	@Override
	public TimeInterval initInterval(@Nullable String prefix, boolean putInModel) {
		final String beginStr, endStr;
		if (prefix == null) {
			beginStr = "interval.begin";
			endStr = "interval.end";
		} else if (prefix.isEmpty()) {
			beginStr = "begin";
			endStr = "end";
		} else if (prefix.charAt(prefix.length() - 1) == '.') {
			beginStr = prefix.concat("begin");
			endStr = prefix.concat("end");
		} else {
			beginStr = prefix.concat(".begin");
			endStr = prefix.concat(".end");
		}
		final String endPara = request.getParameter(endStr);
		Date begin = DateConverter.convertToDate(request.getParameter(beginStr), true),
				end = DateConverter.convertToDate(endPara, true);
		if (begin != null || end != null) {
			TimeInterval interval = new TimeInterval(begin, end);
			if (StringUtil.length(endPara) >= 12) {
				interval.setBeginCalendarField(-1);
				interval.setEndCalendarField(-1);
			}
			if (putInModel) {
				putInModel(prefix, interval);
			}
			return interval;
		}
		return null;
	}

	public static String getAppId(HttpServletRequest request) {
		return request != null ? request.getHeader(Context.internal().getAppIdHeaderName()) : null;
	}

	public static String getOriAppId(HttpServletRequest request) {
		// Ori-App-Id : 原始App-Id   如 h5请求时 Ori-App-Id 为 h5的标记， appId 为 app透传给h5的App-Id
		return request != null ? request.getHeader("Ori-" + Context.internal().getAppIdHeaderName()) : null;
	}

	public WesKit getOriWesKit() {
		return WesKit.ofAppId(getOriAppId(request), false);
	}

	public Client getOriClient() {
		return RequestClientResolver.findClientByAppId(getOriAppId(request));
	}

	public String getAppId() {
		return getAppId(request);
	}

	/**
	 * 获取请求客户端版本号
	 */
	public String getVersion() {
		return getVersion(getAppId());
	}

	public String getChannel() {
		return getChannel(getAppId());
	}

	public String getUserAgent() {
		return request.getHeader("user-agent");
	}

	public String getUA() {
		String cua = getCUA();
		return StringUtil.notEmpty(cua) ? cua : getUserAgent();
	}

	/**
	 * ios 需要自己设置代理
	 */
	public String getCUA() {
		return request.getHeader("c-ua");
	}

	/**
	 * 获取请求客户端名称
	 */
	public String getAppName() {
		return getAppName(getAppId());
	}

	public static String getAppName(@Nullable String appId) {
		return StringUtil.notEmpty(appId) ? StringUtils.substringBefore(appId, "/") : "";
	}

	public static String getChannel(@Nullable String appId) {
		// App-Id："dt_intl_front/iOS/1.1.0/main"
		if (StringUtil.notEmpty(appId)) {
			return StringUtils.substringAfterLast(appId, "/");
		}
		return "main";
	}

	public String getClientId() {
		return request.getHeader("Client-Id");
	}

	/**
	 * 获取请求客户端版本号
	 */
	public static String getVersion(@Nullable String appId) {
		if (StringUtil.notEmpty(appId)) {
			int endPos = appId.lastIndexOf('/');
			if (endPos != -1) {
				int beginPos = appId.lastIndexOf('/', endPos - 1);
				if (beginPos != -1) {
					return appId.substring(beginPos + 1, endPos);
				}
			}
		}
		return "";
	}

	/**
	 * 准备处理邀请码（将邀请码预先存放在 session 中）
	 */
	public final void prepareInviteCode() {
		InternalConfig cfg = Context.internal();
		String inviteCode = getInviteCodeInternal(cfg);
		if (StringUtil.notEmpty(inviteCode)) {
			sessionAttr(cfg.getInviteCodeSessionAttr(), inviteCode);
		}
	}

	/**
	 * 清除 session 中的邀请码
	 */
	public final void clearInviteCode(String inviteCode) {
		if (StringUtil.notEmpty(inviteCode)) {
			removeSessionAttr(Context.internal().getInviteCodeSessionAttr());
		}
	}

	public boolean isFlush() {
		return "1".equals(getParameter("flush"));
	}

	public void exportExcelAttrs(String[] title, List<?> list, boolean excelTitleAsPairs) {
		if (title != null) {
			request.setAttribute(ExportInterceptor.EXPORT_EXCEL_TITLE, title);
		}
		if (list != null) {
			request.setAttribute(ExportInterceptor.EXPORT_EXCEL_LIST, list);
		}
		if (excelTitleAsPairs) {
			request.setAttribute(ExportInterceptor.EXCEL_TITLE_AS_PAIRS, true);
		}
	}

	public boolean isExport() {
		return ExportInterceptor.isExport(request);
	}

	protected static transient Boolean admin;

	/**
	 * 请注意该方法可能返回【不可变】的 Page 实例
	 */
	@Override
	public <T> Page<T> getPage() {
		return getPage(false);
	}

	public <T> Page<T> getPage(boolean allowExportAlready) {
		if (page == null) {
			page = initPage(null);
		}
		if (admin == null) {
			admin = StringUtils.containsIgnoreCase(Context.applicationName(), "admin");
		}
		if ((allowExportAlready || admin) && isExport()) {
			page.setSize(Page.SIZE_SKIP_LIMIT);
		}
		return X.castType(page);
	}

	public void exportExcelAttrs(String[] title, List<?> list) {
		exportExcelAttrs(title, list, false);
	}

	public WesKit wesKit;

	/**
	 * 获取马甲包
	 */
	public WesKit getWesKit() {
		return getWesKit(true);
	}

	public WesKit getWesKit(boolean isDefault) {
		return this.wesKit == null ? this.wesKit = WesKit.ofAppId(getAppId(), isDefault) : this.wesKit;
	}

	public static WesKit getWesKit(HttpServletRequest request, boolean isDefault) {
		return WesKit.ofAppId(getAppId(request), isDefault);
	}

	/** 是否国内版本 */
	public boolean isInterior() {
		return getWesKit().interior;
	}

	/** 是否海外版本 */
	public boolean isOverseas() {
		return !this.isInterior();
	}

	/** 当前登录者是否是当前包用户 */
	public boolean isLoginAppUser() {
		Member user = this.getSessionUser();
		if (user != null) {
			return WesKit.ofIdPrefix(WesKit.calcIdPrefix(user.getId())) == getWesKit();
		}
		return false;
	}

}
